<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
		<meta name="viewport" content="width=device-width,maximum-scale=1,minimum-scale=1,user-scalable=no"/>
		<title>Dojo Touch Testing</title>
		<style type="text/css">
			#test {
				width: 300px;
				height: 150px;
				border: 1px solid #7FB0DB;
				background-color: #7FB0DB;
			}
			#innertest {
				border: 1px solid white;
				width: 100px;
				height: 75px;
				background-color: white;
			}
			#test2 {
				/* for testing touch.move */
				width: 200px;
				height: 50px;
				border: 1px solid yellow;
				background-color: yellow;
			}
			#test3 {
				width: 300px;
				height: 150px;
				border: 1px solid red;
				background-color: red;      
			}
			#innertest3 {
				border: 1px solid white;
				width: 250px;
				height: 75px;
				background-color: white;
			}
			#current, #log {
				width: 300px;
				height: 200px;
				float: left;
			}
			#dohDiv {
				display: none;
				background-color:#800300;
				color: wheat;
			}
		</style>
		<script type="text/javascript" src="../dojo.js" data-dojo-config="async: true"></script>
		<script>
			require([
				"dojo/_base/array",
				"dojo/dom",
				"dojo/_base/lang",
				"dojo/on",
				"dojo/has",
				"doh/runner",
				"dojo/dom-geometry",
				"dojo/dom-style",
				"dojo/domReady",
				"dojo/touch"
			], function(array, dom, lang, on, has, doh, domGeom, domStyle, domReady, touch){

				var action = function(comment, e){
					// summary:
					//		Callback to display into when events fire
					// Detailed log of the most recent event:

					dom.byId("current").innerHTML = "Most recent non touch.move event:";
					var info = "[Touch Event]: " + e.type + " on " + comment +
							"<br/> ------ Event Properties: ------<br/>";
					for(var i in e){
					  if(i == "touches" || i == "targetTouches" || i == "changedTouches"){
						info += i + ": " + e[i].length + "<br/>";
					  }else{
						if(typeof e[i] != "function"){
						  info += " " + i + ": " + e[i] + "<br/>";
						}
					  }
					}
					dom.byId("current").innerHTML += info + "<br/>";

					// This is a log of all events, most recent first:
					dom.byId("log").innerHTML = comment + "{type:" +
							e.type + ", target:" + (e.target.id||e.target.tagName) +
							"}<br/>" + dom.byId("log").innerHTML;

					e.preventDefault();
				};

				var node = dom.byId("test"),
					innerNode = dom.byId("innertest");

				//1. should work well on PC and touch devices
				array.forEach(["test", "innertest"], function(name){
					for(var event in touch){
						if(event != "move"){
							on(dom.byId(name), touch[event], lang.hitch(null, action, "on("+name+", touch."+event+")-->"));
						}
					}
				});

				on(dom.byId("test2"), touch.move, function(e){
					dom.byId("log").innerHTML = "on(touch2, touch.move)--> {type:" +
							e.type + ", target:" + (e.target.id||e.target.tagName) +
							", pageX = " + e.pageX + ", pageY = " + e.pageY +
							"}<br/>" + dom.byId("log").innerHTML;


					// this should stop scrolling
					e.preventDefault();

					// stopPropagation() should work too
					e.stopPropagation();
				});

//					//2. should work well across touch devices
//					on(node, "touchstart", action);
//					on(node, "touchmove", action);
//					on(node, "touchend", action);
//					on(node, "touchcancel", action);
//					on(node, "orientationchange", action);

				dom.byId("test3").dojoClick = true;
				on(dom.byId("test3"), "click", function(e){
					if(has("touch")){
						// click should be a synthetic click
						dom.byId("log").innerHTML = (e._dojo_click ? "Synthetic click received in test3" : "ERROR: native click received in test3") + "<br/>" + dom.byId("log").innerHTML;
					}else{
						// click should be a native click
						dom.byId("log").innerHTML = (e._dojo_click ? "ERROR: Synthetic click received in test3 (non touch device)" : "Native click received in test3  (non touch device)") + "<br/>" + dom.byId("log").innerHTML;
					}
				});
				dom.byId("innertest3").dojoClick = false;
				on(dom.byId("innertest3"), "click", function(e){
					// click should be a native click
					dom.byId("log").innerHTML = (e._dojo_click ? "ERROR: Synthetic click received in innertest3" : "Native click received in innertest3") + "<br/>" + dom.byId("log").innerHTML;;
					e.stopPropagation();
				});

				/**
				 * Fires an event.  All coordinates are defaulted to zero.
				 * @param target the target element.
				 * @param eventType touchstart, touchmove or touchend, or mouse or MSPointer equivalents.
				 */
				function emit(target, eventType, options){
					var targetPos = domGeom.position(target);

					options = lang.mixin({
						pageX: targetPos.x + targetPos.w / 2,
						pageY: targetPos.y + targetPos.h / 2
					}, options || {});

					if(document.createEvent && target.dispatchEvent){
						var touch = {
							identifier: (new Date()).getTime(),
							target: target,
							screenX: 0,
							screenY: 0,
							clientX: 0,
							clientY: 0,
							pageX: 0,
							pageY: 0
						};
						lang.mixin(touch, options || {});

						var mouseEvent = document.createEvent("MouseEvent");
						mouseEvent.initMouseEvent(
								eventType,
								true,
								true,
								target.ownerDocument.defaultView,
								0,
								0,
								0,
								0,
								0,
								false,
								false,
								false,
								false,
								0,
								document.body	// relatedTarget, for mouseout events
						);

						if(/touch/.test(eventType)){
							mouseEvent['touches'] = [touch];
							mouseEvent['targetTouches'] = [touch];
							mouseEvent['changedTouches'] = [touch];
						}

						target.dispatchEvent(mouseEvent);
					}else{
						options.bubbles = true;
						options.cancelable = true;
						on.emit(target, eventType, options);
					}
				}

				// if we declare "dojo/domReady!" touch.js will register its handler *after* the test execution
				// so here we explicitly call domReady.
				domReady(function(){
					var dohDiv = dom.byId('dohDiv');
					domStyle.set(dohDiv, {display: 'block'});

					// Function to register tests on mouse events, touch events, or Microsoft's pointer-ish events
					function register(testName, downEvent, moveEvent, upEvent, cancelEvent){
						doh.register(testName, [
							function press(){
								var executed, target;
								on.once(dohDiv, touch.press, function(e){
									//console.log(e.type);
									executed = true;
									target = e.target;
								});
								emit(dohDiv, downEvent);
								doh.t(executed, 'dojo.touch.press fired');
								doh.is(dohDiv, target, "target");
							},
							function move(){
								var executed, target;
								on.once(dohDiv, touch.move, function(e){
									//console.log(e.type);
									executed = true;
									target = e.target;
								});
								emit(dohDiv, moveEvent);
								doh.t(executed, 'dojo.touch.move fired');
								doh.is(dohDiv, target, "target");
							},
							function release(){
								var executed, target;
								on.once(dohDiv, touch.release, function(e){
									//console.log(e.type);
									executed = true;
									target = e.target;
								});
								emit(dohDiv, upEvent, {screenX: 0, screenY: 50});
								doh.t(executed, 'dojo.touch.release fired');
								doh.is(dohDiv, target, "target");
							},
							function cancel(){
								var executed, target;
								on.once(dohDiv, touch.cancel, function(e){
									executed = true;
									target = e.target;
								});
								emit(dohDiv, cancelEvent, {
									relatedTarget: document.body,	// needed for mouseout event
									screenX: 0,
									screenY: 50,
									pageX: 0,
									pageY: 0
								});
								doh.t(executed, 'dojo.touch.cancel fired');
								doh.is(dohDiv, target, "target");
							},
							function movePreventDefault(){
								/**
								 * checks that calling preventDefault() on dojo "touch.move" event
								 * prevents default behavior on the underlying native event
								 * Ref. #17220
								 * window
								 *    |    =>    (1) listen and prevent default on dojo "touch.move" event
								 *    |    =>    (2) listen and check default behavior status on native "touchmove" event
								 *    |
								 *    +--dohDiv    =>    (3) dispatch native "touchmove" event
								 **/
								var prevented = false;

								// (1) register dojo "touch.move" listener
								on.once(dohDiv, touch.move, function(e){
									e.preventDefault();
									//console.log("prevent default on event " + e.type);
								});

								// (2) register listener for native event (touchmove, mousemove, or MSPointerMove)
								// Call addEventListener() except on IE6-8 where that's not supported
								function listener(e){
									prevented = e.defaultPrevented;
									//console.log("native listener, prevented = " + prevented);
								}
								if(window.addEventListener){
									window.addEventListener(moveEvent, listener);
								}else{
									// IE6-8 code path
									on.once(document.body, moveEvent, listener);
								}

								// (3) dispatch native touchmove/mousemove/MSPointerMove event
								emit(dohDiv, moveEvent);
								doh.t(prevented, 'prevented');

								if(window.addEventListener){
									window.removeEventListener(moveEvent, listener);
								}
							}
						]);
					}

					// Setup tests relevant for this platform
					if(navigator.pointerEnabled){
						register('Pointer events', 'pointerdown', 'pointermove', 'pointerup',
								has('touch') ? 'pointercancel' : 'mouseout');
					}else if(navigator.msPointerEnabled){
						register('MSPointer events', 'MSPointerDown', 'MSPointerMove', 'MSPointerUp',
								has('touch') ? 'MSPointerCancel' : 'mouseout');
					}else{
						// Mouse is always supported, even on devices with touch capability.
						// Test mouse first because once we start emitting touch events, dojo/touch ignores mouse events
						// for 1000ms.
						register('mouse events', 'mousedown', 'mousemove', 'mouseup', 'mouseout');

						if(has("touch")){
							register('touch events', 'touchstart', 'touchmove', 'touchend', 'touchcancel');
						}
					}

					if(has("touch")){
						doh.registerTest("synthetic clicks", {
			                name: "Synthetic click disabled",
			                timeout: 1000,
			                runTest: function(){
								/**
								 * check that synthetic click is NOT fired when dojoClick value is set
								 * to falsy on a dom element and touch is released inside the element.
								 * Note that synthetic click is fired ONLY on touch enabled devices (touch or MSPointer).
								 */
								var domEltWithDisabledSyntheticClick = dom.byId("innertest3");
								var box = domEltWithDisabledSyntheticClick.getBoundingClientRect(); // position in viewport coordinates
								var coordInsideEltWithDisabledSyntheticClick = {x: box.right - box.left, y:box.bottom - box.top};
								var clicked = false;
								// register the click handler
								function listener(e){
									alert("click fired ??");
									clicked = true;
								}
								domEltWithDisabledSyntheticClick.addEventListener("click", listener);
								// emit "touchstart" and "touchend" events inside the element
								emit(domEltWithDisabledSyntheticClick, "touchstart", {screenX: coordInsideEltWithDisabledSyntheticClick.x, screenY: coordInsideEltWithDisabledSyntheticClick.y});
								emit(domEltWithDisabledSyntheticClick, "touchend", {screenX: coordInsideEltWithDisabledSyntheticClick.x, screenY: coordInsideEltWithDisabledSyntheticClick.y});
								var deferred = new doh.Deferred();
								// without deferred the click handler is called after the doh method ends.
								setTimeout(deferred.getTestCallback(function(){
									doh.t(!clicked, 'synthetic click fired');
								}), 0);
								return deferred;
			                }
						});
					}

					doh.run();
				});
			});
		</script>
	</head>
	<body>
		<div id="test">
			test
			<div id="innertest">
				inner test
			</div>
		</div>
		<div id="test2">
			touch.move
		</div>
		<div id="test3">
			On touch devices, synthetic clicks are enabled in this area.
			<div id="innertest3">
				On touch devices, synthetic clicks disabled in this area.
			</div>
		</div>
		<div id="dohDiv">doh</div>
		<div id="current"></div>
		<div id="log"></div>
		<br style="clear:both"/>
	</body>
</html>
